/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.stemaini.core.doc;

import com.stemaini.core.database.*;
import com.stemaini.core.stem.Kata;
import com.stemaini.utility.Koneksi;
import com.stemaini.core.stem.Kata;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.stemaini.utility.Koneksi;
import taini.koneksi.KoneksiAini;

/**
 *
 * @author AdhiK
 */
public class Vektor {
    private KoneksiAini theKoneksi; //kelas koneksi ke database
    private LinkedList listTerm;
    private Kamus kamus;
    private Terms termDB;
    private String idDok;
    
    public Vektor()
    {
        this.listTerm = new LinkedList();
    }
    
    public Vektor(String idDok, KoneksiAini theKoneksi)
    {
        this.idDok = idDok;
        this.theKoneksi = theKoneksi;
        this.listTerm = new LinkedList();
    }
    
    public Vektor(String idDok, Terms termDB, Kamus kamus)
    {
        this.idDok = idDok;
        this.theKoneksi = kamus.getKoneksi();
        this.kamus = kamus;
        this.termDB = termDB;
        this.listTerm = new LinkedList();
    }
    
        
    public int getSize()
    {
        return this.listTerm.size();
    }

    public int getTermId(int i)
    {
        VektorNode vn = (VektorNode)listTerm.get(i);
        return vn.getIdTerm();
    }
    public VektorNode getTermNode(int i)
    {
        return (VektorNode)listTerm.get(i);
    }
    
    public String getTermNodeKata(int i)
    {
        VektorNode tm = (VektorNode)listTerm.get(i);
        return tm.getWord();
    }
    
    public int getTermNodeFrekuensi(int i)
    {
        VektorNode tm = (VektorNode)listTerm.get(i);
        return tm.getFreq();
    }
    
    public double getTermNodeBobot(int i)
    {
        VektorNode tm = (VektorNode)listTerm.get(i);
        return tm.getBobot();
    }
    
    //untuk semua method addTerm, harus ditambahkan fitur grouping!!!
    public void addTerm(String kata, int freq)
    {
        VektorNode baru = new VektorNode(kata,freq);
        addTermNGrouping(baru);
    }
    
    public void addTerm(String kata, int freq, double bobot)
    {
        VektorNode baru = new VektorNode(kata,freq,bobot);
        addTermNGrouping(baru);
    }
    
    public void addTerm(String kata, int freq, int id, double bobot)
    {
        VektorNode baru = new VektorNode(kata,freq,id,bobot);
        addTermNGrouping(baru);
    }
    
    private void addTermNGrouping(VektorNode baru)
    {
        for(int j=0; j<listTerm.size(); j++){
            VektorNode vn = (VektorNode)listTerm.get(j);
            if(vn.getWord().equalsIgnoreCase(baru.getWord())){
                vn.setFreq(vn.getFreq()+1);
                return;
            }
        }
        listTerm.add(baru);
    }
    
    /**
     * mengelompokkan term-term yg sama ke dalam satu term node saja 
     * (+ mengupdate jumlah frekuensinya dgn total keseluruhan frekuensi term2 tsb)
     */
    private void listTermGrouping()
    {
        int count =0 , j; 
        for(int i=0; i<listTerm.size(); i++)
        {
            count = 0;  j=i+1;
            VektorNode tm = (VektorNode)listTerm.get(i);
            
            //dihitung dulu
            while(j<listTerm.size())
            {
                VektorNode tm2 = (VektorNode)listTerm.get(j);
                if(tm2.getWord().equalsIgnoreCase(tm.getWord())){
                    count+=tm2.getFreq(); 
                    listTerm.remove(j);
                }
                else
                    j++;
            }
            tm.setFreq(tm.getFreq()+count);
        }
    }
    
    /**
     * stem semua term pada listTerm lalu mengelompokkannya dgn memanggil 
     * makeListTermDistinct();
     */
    public synchronized void stemListTerm(int pilihanStemmer)
    {
        for(int i=0; i<listTerm.size() ; i++)
        {
            VektorNode tm = (VektorNode)listTerm.get(i);
            Kata kata = new Kata(tm.getWord(), this.kamus);
            tm.setWord(kata.getBentukDasar(pilihanStemmer));
        }
        this.listTermGrouping();
    }
    
    /**
     * method void syncVektorWithTerms()
     * sangat disarankan untuk dijalankan stelah TermGrouping & stemming,
     * Selain itu,untuk menghindari dimasukkannya kata-kata yg sbenarnya berkata-dasar
     * sama ke dalam database Terms.
     */
    public void syncWithTermsClass()
    {
        for(int i=0; i<this.getSize(); i++)
        {
            VektorNode vn = (VektorNode)this.getTermNode(i);
            if(termDB.isContain(vn.getWord())){
                //update ID_Term pada Vektor
                vn.setIdTerm(termDB.getTermsNodeID(vn.getWord()));
            } 
            else{
                //buat di terms
                termDB.append(vn.getWord());
                vn.setIdTerm(termDB.getTermsNodeID(vn.getWord()));
            }
            
        }
    }

    public void importIdTerm()
    {
        for(int i = 0; i < this.getSize();i++)
        {
            VektorNode vn = (VektorNode)this.getTermNode(i);
            String sql = "SELECT id_term FROM TERMS WHERE nama_term = '"+vn.getWord()+"'";
            try
            {
                ResultSet rs = theKoneksi.executeSelect(sql);
                if(rs.next())
                {
                    vn.setIdTerm(rs.getInt(1));
                }
                else
                {
                    int newID = 0;
                    sql = "SELECT max( id_term ) FROM TERMS";
                    rs = theKoneksi.executeSelect(sql);
                    if(rs.next())
                    {
                        newID = rs.getInt(1)+1;
                        vn.setIdTerm(newID);
                    }
                    sql = "INSERT INTO TERMS (id_term, nama_term) VALUES ("+newID+",'"+vn.getWord()+"')";
                    theKoneksi.executeUpdate(sql);
                    //System.out.println(sql);
                }
            }
            catch (SQLException ex) {
                Logger.getLogger(Vektor.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalStateException ex) {
                Logger.getLogger(Vektor.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
    }

    public synchronized void importTermFromDbase()
    {
        try {
            String s = "Select VEKTOR.ID_TERM, TERMS.NAMA_TERM," +
                    "VEKTOR.FREKUENSI, VEKTOR.BOBOT " +
                    "from VEKTOR,TERMS where VEKTOR.ID_DOK=" 
                    + idDok +" and VEKTOR.ID_TERM = TERMS.ID_TERM" +
                    " order by VEKTOR.ID_TERM";
            //System.out.println(s);
            ResultSet rs = theKoneksi.executeSelect(s);
            if(rs.first())
            {
                this.listTerm.clear();
                while(!rs.isAfterLast())
                {
                    this.addTerm(rs.getString("NAMA_TERM"), 
                            rs.getInt("FREKUENSI"), rs.getInt("ID_TERM"), 
                            rs.getInt("BOBOT"));
                    rs.next();
                }
            }
            
        } catch (SQLException ex) {
            Logger.getLogger(Vektor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalStateException ex) {
            Logger.getLogger(Vektor.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public void exportToDbase2()
    {
        try {
            //1. ID untuk tiap term di kelas VEKTOR ini,
            //harus disamakan dengan ID term-term pada kelas TERMS.
            this.syncWithTermsClass();

            //2. Barulah term-term di kelas VEKTOR ini bisa dideploy ke database
            String s = "INSERT INTO VEKTOR(ID_DOK,ID_TERM,FREKUENSI,BOBOT) " +
                       "VALUES(?,?,?,?)";
            PreparedStatement ps = theKoneksi.persiapkanStatement(s);
            int count=0;
            for(int i=0; i<this.getSize(); i++)
            {
                VektorNode v = this.getTermNode(i);
                ps.setInt(1, Integer.parseInt(this.idDok));
                ps.setInt(2, v.getIdTerm() );
                ps.setInt(3, v.getFreq());
                ps.setDouble(4, v.getBobot());
                ps.addBatch();count++;
                if(count==150){
                    count=0;ps.executeBatch();ps.clearBatch();
                }
            }
            if(count!=0)
                ps.executeBatch();
            
          
        } catch (SQLException ex) {
            Logger.getLogger(Dokumen.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public synchronized void exportToDbaseAini()
    {
        this.importIdTerm();
        String s = "";
        for(int i = 0; i <this.getSize();i++)
        {
            VektorNode vn = this.getTermNode(i);
            //System.out.println(s);
            try {
                s = "SELECT * FROM VEKTOR WHERE ID_DOK ="+this.idDok+" AND ID_TERM = "+vn.getIdTerm();
                ResultSet rs = theKoneksi.executeSelect(s);
                if(!rs.next())
                {
                    s = "INSERT INTO VEKTOR(ID_DOK,ID_TERM,FREKUENSI,BOBOT) VALUES "+"("+this.idDok+","+vn.getIdTerm()+","+vn.getFreq()+","+vn.getBobot()+")";
                    theKoneksi.executeUpdate(s);
                }
            } catch (SQLException ex) {
                Logger.getLogger(Vektor.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalStateException ex) {
                Logger.getLogger(Vektor.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }


    public synchronized void exportToDbase()
    {
        //try
        {
            //1. ID untuk tiap term di kelas VEKTOR ini,
            //harus disamakan dengan ID term-term pada kelas TERMS.
            //this.syncWithTermsClass();
            this.importIdTerm();
            //3. Barulah term-term di kelas VEKTOR ini bisa dideploy ke database
            String s = "INSERT INTO VEKTOR(ID_DOK,ID_TERM,FREKUENSI,BOBOT) VALUES";

            int count=0;
            for(int i=0; i<this.getSize(); i++)
            {
                VektorNode v = this.getTermNode(i);
                s = s + "(";
                
                s = s + this.idDok + ",";
                
                s = s + v.getIdTerm() + ",";
                
                s = s + v.getFreq() + ",";
                
                s = s + v.getBobot() + ")";

                count++;
                if(count==150){
                    s = s + ";";
                    count=0;
                    //theKoneksi.executeUpdate(s);
                    s = "INSERT INTO VEKTOR(ID_DOK,ID_TERM,FREKUENSI,BOBOT) VALUES";
                }else{
                    if(i!=getSize()-1)
                        s = s + ",";
                }
            }
            if(count!=0){
                s = s + ";";
                //theKoneksi.executeUpdate(s);
            }  
        }
        //catch (SQLException ex) {
        //    Logger.getLogger(Dokumen.class.getName()).log(Level.SEVERE, null, ex);
        //}
    }
    
    /**
     * getTermStatsToString()
     * @return terms <String>
     */
    public String getTermStatsToString() {
        String temp="";
        for(int i=0;i<listTerm.size();i++){
            temp += ((VektorNode)listTerm.get(i)).getWord() + " " +
                    ((VektorNode)listTerm.get(i)).getFreq() + "\n";
        }
        return temp;
    }
    
    public double getFreqSumAllTerms()
    {
        double sum = 0;
        if(listTerm!=null){
            for(int i=0; i<listTerm.size();i++)
            {
                sum += this.getTermNodeFrekuensi(i);
            }
        }
        return sum;
    }
    
    public double getBobotSumAllTerms()
    {
        double sum = 0;
        if(listTerm!=null){
            for(int i=0; i<listTerm.size();i++)
            {
                sum += this.getTermNodeBobot(i);
            }
        }
        return sum;
    }
    
}
